Attackers exploit software vulnerabilities to control or crash programs. This is a serious problem because software can have many vulnerabilities and attacks can be frequent. Techniques have therefore been developed to protect against such attacks. Some techniques detect attacks by adding checks to programs: safe languages include checks to ensure type safety and they throw exceptions when the checks fail (e.g. Java and C#), and checks can be added transparently to programs written in unsafe languages. However, these techniques add significant overhead because the checks are performed whilst the software is running and often detect attacks too late when the only way to recover may be to restart the program. Other techniques use filters to filter out malicious input messages. These filters may be computed centrally using symbolic execution along the path taken by a sample malicious input. Having generated such a filter, it may be shared with other users of the program so that similar attacks can be prevented. However, attackers can bypass these filters by generating exploits that follow a different execution path.